package com.fanco.learn_datastruct_leetcode.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class ReflectionTest {
    public static void main(String[] args) {

        try {
            Class clazz = Class.forName("com.jishucai.reflection.Student");
            Object o = clazz.getDeclaredConstructor().newInstance();

            /**
             * 获取类的构造器
             */
            // 1. 获取单个构造函数，通过传递参数，不分public和非public
            Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);

            System.out.println("获取参数为String的非public构造器");
            System.out.println(declaredConstructor.getName());
            System.out.println(declaredConstructor.getParameterTypes());

            // 2. 获取单个构造函数，通过传递参数，只获取public
            Constructor constructor = clazz.getConstructor(String.class);
            System.out.println("获取单个类型为public的构造器");
            System.out.println(constructor.getName());
            System.out.println(constructor.getParameterTypes());

            // 3. 获取所有的public构造器
            Constructor[] constructors = clazz.getConstructors();
            System.out.println("获取所有的public构造器");
            for (int i = 0; i < constructors.length; i++) {
                System.out.println(constructors[i].getName());
            }

            // 4. 获取所有的构造器
            System.out.println("获取所有的构造器");
            Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
            for (int i = 0; i < declaredConstructors.length; i++) {
                System.out.println(declaredConstructors[i].getName());
            }


            /**
             * 获取类的方法
             */
            System.out.println("获取类的所有方法（不止public）");
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (int i = 0; i < declaredMethods.length; i++) {
                System.out.println(declaredMethods[i].getName());
            }

            System.out.println("获取类的所有public方法");
            Method[] methods = clazz.getMethods();
            for (int i = 0; i < methods.length; i++) {
                System.out.println(methods[i].getName());
            }

            System.out.println("获取单个指定参数，指定名称的方法");
            Method testStudent = clazz.getDeclaredMethod("testStudent");
            System.out.println(testStudent.getName());

            System.out.println("获取单个指定参数，指定名称的public方法");
            Method setSex = clazz.getMethod("setSex", int.class);
            System.out.println(setSex.getName());

            System.out.println("通过method调用方法,public");
            setSex.invoke(o, 10);
            System.out.println(((Student) o).getSex());

            System.out.println("通过method调用方法,private");
            testStudent.setAccessible(true);
            testStudent.invoke(o);

            /**
             * 获取类的成员变量
             */
            System.out.println("获取类的单个成员变量（不止public）");
            Field studentName = clazz.getDeclaredField("studentName");
            System.out.println(studentName.getType());

            System.out.println("获取类的单个成员变量public");
            Field studentName1 = clazz.getField("intro");
            studentName1.setAccessible(true);
            System.out.println(studentName1.getType());

            System.out.println("获取所有的成员变量（不止public）");
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                System.out.println(field.getName());
            }

            System.out.println("获取所有的成员变量（仅public）");
            Field[] fields = clazz.getFields();
            for (Field field : fields) {
                System.out.println(field.getName());
            }

            // 获取方法 构造器  变量的 修饰域
            System.out.println("获取指定对象的修饰域");
            System.out.println(Modifier.toString(studentName.getModifiers()));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
